package figuras.malla;

import java.util.ArrayList;

import figuras.BSplines;
import figuras.PuntoVector;

public class MallaPorSplineYRevolucion extends Malla {

	public MallaPorSplineYRevolucion(BSplines bspline, double radianes,
			int pasos, boolean esPistilo) {
		aproximaSplineYCrea(bspline, radianes, pasos, esPistilo);
	}

	public void aproximaSplineYCrea(BSplines bspline, double radianes,
			int pasos, boolean esPistilo) {
		ArrayList<PuntoVector> puntosDeControl = bspline.getPuntosControl();
		// aproximar por Spline
		int n = puntosDeControl.size();
		// BSplines b=new BSplines();
		bspline.setPuntosControl(puntosDeControl);
		ArrayList<PuntoVector> perfil = bspline.aproxima(2, n, pasos);
		PuntoVector limiteArriba = new PuntoVector(0, perfil.get(0).getY(), 0,
				1);
		PuntoVector limiteAbajo = new PuntoVector(0, perfil.get(
				perfil.size() - 1).getY(), 0, 1);
		perfil.add(0, limiteArriba);
		perfil.add(limiteAbajo);
		if (esPistilo) {
			PuntoVector origen = new PuntoVector(0, 0, 0, 1);
			PuntoVector puntoBase = perfil.get(perfil.size() - 1);
			PuntoVector trasladaOrigen = puntoBase.obtenVector(origen);
			for (PuntoVector p : perfil) {
				p.setX(p.getX() + trasladaOrigen.getX());
				p.setY(p.getY() + trasladaOrigen.getY());
				p.setZ(p.getZ() + trasladaOrigen.getZ());
			}
		}
		bspline.setPerfil(perfil);
		n = pasos + 1 + 2;
		// revolucionar perfil
		int verticesRot = (int) (2 * Math.PI / radianes);
		nCaras = (n - 1) * (verticesRot) * 2;
		nVertices = verticesRot * n;
		nNormales = nCaras;
		vertices = new PuntoVector[nVertices];
		normales = new PuntoVector[nNormales];
		caras = new Cara[nCaras];
		int contador = 0;

		for (int i = 0; i < n; i++) {
			PuntoVector origen = perfil.get(i);
			double anguloIni = Math.atan2(origen.getZ(), origen.getX());

			for (int j = 0; j < verticesRot; j++) {
				double angulo = anguloIni + radianes * j;
				PuntoVector destino = new PuntoVector(0.0f, origen.getY(),
						0.0f, 1);
				double radio = origen.distancia(destino);
				double z = radio * Math.sin(angulo);
				double x = radio * Math.cos(angulo);
				double y = origen.getY();
				vertices[j * n + i] = new PuntoVector((float) x, (float) y,
						(float) z, 1);

				if ((i > 0) && (j > 0)) {
					ArrayList<VerticeNormal> vector = new ArrayList<VerticeNormal>();
					vector.add(new VerticeNormal((j * n + i) % nVertices,
							contador));
					vector.add(new VerticeNormal(((j - 1) * n + i) % nVertices,
							contador));
					vector.add(new VerticeNormal((j * n + (i - 1)) % nVertices,
							contador));
					caras[contador] = new Cara(3, vector);
					normales[contador] = caras[contador].calculaNormal(
							vertices, contador);
					contador++;

					vector = new ArrayList<VerticeNormal>();
					vector.add(new VerticeNormal(((j - 1) * n + i) % nVertices,
							contador));
					vector.add(new VerticeNormal(((j - 1) * n + (i - 1))
							% nVertices, contador));
					vector.add(new VerticeNormal((j * n + (i - 1)) % nVertices,
							contador));
					caras[contador] = new Cara(3, vector);
					normales[contador] = caras[contador].calculaNormal(
							vertices, contador);
					contador++;

					if (j == verticesRot - 1) {
						vector = new ArrayList<VerticeNormal>();
						vector.add(new VerticeNormal((j * n + i) % nVertices,
								contador));
						vector.add(new VerticeNormal((j * n + (i - 1))
								% nVertices, contador));
						vector.add(new VerticeNormal(((j + 1) * n + i)
								% nVertices, contador));
						caras[contador] = new Cara(3, vector);
						normales[contador] = caras[contador].calculaNormal(
								vertices, contador);
						contador++;

						vector = new ArrayList<VerticeNormal>();
						vector.add(new VerticeNormal((j * n + (i - 1))
								% nVertices, contador));
						vector.add(new VerticeNormal(((j + 1) * n + (i - 1))
								% nVertices, contador));
						vector.add(new VerticeNormal(((j + 1) * n + i)
								% nVertices, contador));
						caras[contador] = new Cara(3, vector);
						normales[contador] = caras[contador].calculaNormal(
								vertices, contador);
						contador++;
					}
				}
			}
		}
	}
}
